#!/usr/bin/perl

# $Id: get_disk 163 2013-04-17 07:40:16Z chengxin.cai $

use strict;
use File::Basename;
use Carp;
use Switch;

use PerlUtil qw(time_section);

my %cmd = (
    multipath => '/sbin/multipath',
    lsscsi    => '/usr/bin/lsscsi',
    fdisk     => '/sbin/fdisk',
    sg_inq    => '/usr/bin/sg_inq',
);

if (@ARGV == 0) { exit 0; }

for my $disk (@ARGV) {
    my $dev = time_section( "Make device", \&make_device, $disk );
    &{ &$dev('show') };
}

sub make_device {
    my $param = shift;

    my ($disk, $mpath, $uuid);

    chomp( my @mpathlines = `$cmd{multipath} -l $param` );
    my @fields = split /\s+/, $mpathlines[0];

    switch ($param) {
        case ( /^\/dev/ )  { 
            $disk  = $param; 
            $mpath = $fields[0];
            ($uuid = $fields[1]) =~ s/[\(\)]//g;
        }
        case ( /^mpath/ ) { 
            $disk  = get_disk_from_mpathlines(@mpathlines);
            $mpath = $param; 
            ($uuid = $fields[1]) =~ s/[\(\)]//g;
        }
        case ( /3600[a-f0-9]{29}/ ) {
            $disk  = get_disk_from_mpathlines(@mpathlines);
            $mpath = $fields[0];
            $uuid  = $param;
        }
        else { 
            croak "Invalid parameter for make_device: $param"; 
        }
    }

    my $dm = $fields[2];

    chomp( my $cmdout = `$cmd{sg_inq} -p0x83 $disk` );
    my $wwn = $1 if ( $cmdout =~ /\[0x([0-9a-f]{16})\]/ );

    chomp( my $lunline = `$cmd{lsscsi} | grep -w $disk` );
    ( my $lun = (split /\s+/, $lunline)[0] ) =~ s/.*:([0-9]+).*/$1/;

    chomp( my $msafile = `grep -l $wwn /home/lunmgr/msa_xml/*` );

    ( my $msa = basename($msafile) ) =~ s/\.xml//;
    
    #get partitions
    chomp( my @cmdouts = `$cmd{fdisk} -l $disk | grep ^$disk` );
    my @parts = map { (split /\s+/, $_)[0] } @cmdouts;

    my $show = sub {
        print "{\n",
             qq{    "disk"  : "$disk",\n},
             qq{    "mpath" : "$mpath",\n},
             qq{    "uuid"  : "$uuid",\n},
             qq{    "dm"    : "$dm",\n},
             qq{    "wwn"   : "$wwn",\n},
             qq{    "lun"   : "$lun",\n},
             qq{    "msa"   : "$msa",\n},
             qq{    "parts" : ["} . join('","', @parts) . qq{"]\n},
              "}\n";
    };

    return sub {
        my $op = shift;

        switch ($op) {
            case 'disk'  { return $disk;  }
            case 'uuid'  { return $uuid;  }
            case 'mpath' { return $mpath; }
            case 'dm'    { return $dm;    }
            case 'wwn'   { return $wwn;   }
            case 'lun'   { return $lun;   }
            case 'msa'   { return $msa;   }
            case 'parts' { return @parts; }
            case 'show'  { return $show;  }
            else { croak 'Invalid operation:' . $op; }
        }
    }
}

sub get_disk_from_mpathlines {
    my @mpathlines = @_;
    my @disklines = grep {/sd[a-z]+/} @mpathlines;

    $disklines[0] =~ /(sd[a-z]+)/;

    return '/dev/' . $1;
}

